#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
一个把所有常用类定义都“跑一遍”的示例
运行：python demo_all_class_features.py
"""

import random
from time import sleep


class Robot:
    """1. 文档字符串：这是 Robot 类的说明"""

    # 2. 类变量 —— 所有机器人共享
    factory = "CyberDyne"
    __counter = 0  # 私有类变量，记录共创建了多少台

    # 3. 内存优化：限定实例能绑定的属性（可选）
    __slots__ = ("__id", "name", "_energy", "__task")

    # 4. 构造实例对象（比 __init__ 更早）
    def __new__(cls, name):
        print(f"  【__new__】正在制造一台新 {cls.__name__}")
        return super().__new__(cls)

    # 5. 初始化实例属性
    def __init__(self, name):
        Robot.__counter += 1
        self.__id = f"{name}-{random.randint(1000, 9999)}"  # 8. 私有变量
        self.name = name
        self._energy = 100  # 7. “受保护”惯例
        self.__task = None
        print(f"  【__init__】机器人 <<{self.name}>> 已就绪，ID={self.__id}")

    # 9. 静态方法：与类/实例都无绑定，纯工具
    @staticmethod
    def help():
        print("  【静态方法】Robot 使用说明书：充电、工作、销毁")

    # 10. 类方法：第一个参数是 cls，常用作“工厂”
    @classmethod
    def create_anonymous(cls):
        print("  【类方法】生产一台匿名机器人")
        return cls("Anonymous")

    # 11. 只读属性 —— 能量百分比
    @property
    def energy(self):
        return self._energy

    # 12. 可写属性 —— 任务名
    @property
    def task(self):
        return self.__task

    @task.setter
    def task(self, value):
        if not value:
            raise ValueError("任务不能为空")
        self.__task = value
        print(f"  【setter】任务已更新为：{value}")

    @task.deleter
    def task(self):
        print("  【deleter】清除任务")
        self.__task = None

    # 16. 支持内置 len()
    def __len__(self):
        return self._energy

    # 17. 支持 obj[key] 读写删
    def __getitem__(self, key):
        if key == "id":
            return self.__id
        if key == "name":
            return self.name
        raise KeyError(key)

    def __setitem__(self, key, value):
        if key == "name":
            self.name = value
        else:
            raise KeyError(key)

    def __delitem__(self, key):
        if key == "name":
            print("  【__delitem__】名字被删掉了，将重置为 Unknown")
            self.name = "Unknown"
        else:
            raise KeyError(key)

    # 18. 让实例像函数一样被调用
    def __call__(self, hours=1):
        print(f"  【__call__】机器人 <<{self.name}>> 开始工作 {hours} 小时")
        cost = hours * 10
        self._energy = max(0, self._energy - cost)
        if self._energy == 0:
            print("    能量耗尽，需要充电！")

    # 19. 打印/调试时看到的内容
    def __repr__(self):
        return f"Robot(name={self.name}, energy={self._energy})"

    # 20. 析构（垃圾回收时调用，时机不确定）
    def __del__(self):
        Robot.__counter -= 1
        print(f"  【__del__】机器人 <<{self.name}>> 被销毁，剩余数量={Robot.__counter}")

    # 14. 上下文管理器协议 —— with 语句
    def __enter__(self):
        print("  【__enter__】进入上下文：机器人自动开机")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("  【__exit__】退出上下文：自动关机并保存日志")
        # 如果有异常，exc_type 不为 None
        if exc_type:
            print(f"    异常类型：{exc_type.__name__}，已记录")

    # 15. 迭代器协议 —— 让机器人能“自充电”
    def __iter__(self):
        print("  【__iter__】开始迭代充电过程")
        return self

    def __next__(self):
        if self._energy >= 100:
            raise StopIteration("电量已满，停止充电")
        self._energy += 10
        print(f"    充电中… 当前能量={self._energy}")
        return self._energy

    # 嵌套类 —— 纯命名空间
    class Config:
        max_energy = 100
        low_battery = 20


# -------------------- 下面是“全部调用”演示 --------------------
def main():
    print("=== 1. 制造机器人 ===")
    r = Robot("T800")
    sleep(0.5)

    print("\n=== 2. 类变量 & 静态方法 ===")
    print("工厂名：", Robot.factory)
    Robot.help()

    print("\n=== 3. 类方法造匿名机器人 ===")
    anon = Robot.create_anonymous()
    sleep(0.5)

    print("\n=== 4. property 三兄弟 ===")
    print("当前能量：", r.energy)
    r.task = "保卫地球"
    print("任务名：", r.task)
    del r.task

    print("\n=== 5. 模拟函数调用 ===")
    r(2)  # 工作 2 小时
    print("工作后能量：", r.energy)

    print("\n=== 6. 像字典一样读写删 ===")
    print("r['id'] =", r["id"])
    r["name"] = "T1000"
    print("改名后：", r)
    del r["name"]
    print("删除名字后：", r)

    print("\n=== 7. 内置 len() ===")
    print("len(r) =", len(r))

    print("\n=== 8. 上下文管理器 with ===")
    with Robot("WithBot") as bot:
        bot.task = "临时任务"
        bot(1)

    print("\n=== 9. 迭代器：自充电 ===")
    r._energy = 50  # 先耗到 50
    for e in r:
        pass
    print("充满后 len(r) =", len(r))

    print("\n=== 10. 嵌套类配置 ===")
    print("最大能量：", Robot.Config.max_energy)
    print("低电量阈值：", Robot.Config.low_battery)

    print("\n=== 11. 查看对象列表 ===")
    print("当前机器人总数（私有类变量）", Robot._Robot__counter)

    print("\n=== 12. 即将销毁，观察 __del__ ===")
    # 删除引用，方便观察析构

    print(type(r))

    del anon
    del r
    sleep(0.5)

    print("\n=== 运行结束 ===")


if __name__ == "__main__":
    main()
